package com.share.device.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.xiaoymin.knife4j.core.util.CollectionUtils;
import com.share.common.core.exception.ServiceException;
import com.share.common.security.utils.SecurityUtils;
import com.share.device.domain.Cabinet;
import com.share.device.domain.CabinetSlot;
import com.share.device.domain.CabinetType;
import com.share.device.domain.PowerBank;
import com.share.device.mapper.CabinetMapper;
import com.share.device.mapper.CabinetSlotMapper;
import com.share.device.mapper.CabinetTypeMapper;
import com.share.device.service.ICabinetService;
import com.share.device.service.IPowerBankService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class CabinetServiceImpl extends ServiceImpl<CabinetMapper, Cabinet> implements ICabinetService {


    private final CabinetTypeMapper cabinetTypeMapper;

    private final CabinetSlotMapper cabinetSlotMapper;

    private final IPowerBankService powerBankService;


    /**
     * 查询充电宝柜机列表（优化版）
     */
    @Override
    @Transactional(readOnly = true)
    public List<Cabinet> selectCabinetList(Cabinet cabinet) {
        // 构建柜机查询条件
        LambdaQueryWrapper<Cabinet> queryWrapper = buildCabinetQueryWrapper(cabinet);
        List<Cabinet> cabinetList = baseMapper.selectList(queryWrapper);

        if (CollUtil.isEmpty(cabinetList)) {
            return Collections.emptyList();
        }

        // 批量查询柜机类型，避免N+1问题
        setCabinetTypeNames(cabinetList);

        return cabinetList;
    }

    /**
     * 新增充电宝柜机
     *
     * @param cabinet 柜机实体对象，包含基本信息
     * @return 操作结果（1表示成功）
     * @throws ServiceException 若柜机编号已存在
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int saveCabinet(Cabinet cabinet) {
        // 校验柜机编号唯一性
        long count = this.count(new LambdaQueryWrapper<Cabinet>().eq(Cabinet::getCabinetNo, cabinet.getCabinetNo()));
        if (count > 0) {
            throw new ServiceException("该柜机编号已存在");
        }

        // 根据柜机类型id查询柜机类型
        CabinetType cabinetType = cabinetTypeMapper.selectById(cabinet.getCabinetTypeId());

        // 设置柜机基本信息：总插槽数、可用插槽数等
        cabinet.setTotalSlots(cabinetType.getTotalSlots());
        cabinet.setFreeSlots(cabinetType.getTotalSlots());
        cabinet.setUsedSlots(0);
        cabinet.setAvailableNum(0);
        cabinet.setCreateTime(new Date());
        cabinet.setCreateBy(SecurityUtils.getUsername());

        // 保存柜机主信息
        this.save(cabinet);

        // 初始化柜机插槽：为每个插槽创建记录
        int size = cabinetType.getTotalSlots();
        for (int i = 0; i < size; i++) {
            CabinetSlot cabinetSlot = new CabinetSlot();
            cabinetSlot.setCabinetId(cabinet.getId());
            cabinetSlot.setSlotNo(i + 1 + ""); // 插槽编号从1开始
            cabinetSlot.setCreateTime(new Date());
            cabinetSlot.setCreateBy(SecurityUtils.getUsername());
            cabinetSlotMapper.insert(cabinetSlot);
        }

        return 1;
    }

    /**
     * 修改充电宝柜机信息
     *
     * @param cabinet 柜机实体对象，包含要修改的信息
     * @return 操作结果（1表示成功）
     * @throws ServiceException 若柜机已投放使用或编号已存在
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateCabinet(Cabinet cabinet) {
        // 获取旧的柜机信息
        Cabinet oldCabinet = this.getById(cabinet.getId());
        if (oldCabinet != null && !"0".equals(oldCabinet.getStatus())) {
            throw new ServiceException("该柜机已投放，无法修改");
        }

        // 判断柜机编号是否改变，若改变则校验新编号唯一性
        if (!oldCabinet.getCabinetNo().equals(cabinet.getCabinetNo())) {
            long count = this.count(new LambdaQueryWrapper<Cabinet>().eq(Cabinet::getCabinetNo, cabinet.getCabinetNo()));
            if (count > 0) {
                throw new ServiceException("该柜机编号已存在");
            }
        }

        // 判断是否修改了柜机类型
        if (!Objects.equals(oldCabinet.getCabinetTypeId(), cabinet.getCabinetTypeId())) {
            // 根据新的柜机类型id查询柜机类型
            CabinetType cabinetType = cabinetTypeMapper.selectById(cabinet.getCabinetTypeId());

            // 更新柜机容量信息
            cabinet.setTotalSlots(cabinetType.getTotalSlots());
            cabinet.setFreeSlots(cabinetType.getTotalSlots());
            cabinet.setUsedSlots(0);
            cabinet.setAvailableNum(0);
            cabinet.setUpdateTime(new Date());
            cabinet.setUpdateBy(SecurityUtils.getUsername());
            this.updateById(cabinet);

            // 重新初始化插槽：删除原有插槽并创建新插槽
            cabinetSlotMapper.delete(new LambdaQueryWrapper<CabinetSlot>().eq(CabinetSlot::getCabinetId, cabinet.getId()));
            int size = cabinetType.getTotalSlots();
            for (int i = 0; i < size; i++) {
                CabinetSlot cabinetSlot = new CabinetSlot();
                cabinetSlot.setCabinetId(cabinet.getId());
                cabinetSlot.setSlotNo(i + 1 + "");
                cabinetSlot.setCreateTime(new Date());
                cabinetSlot.setCreateBy(SecurityUtils.getUsername());
                cabinetSlotMapper.insert(cabinetSlot);
            }
        } else {
            // 仅更新基本信息
            cabinet.setUpdateTime(new Date());
            cabinet.setUpdateBy(SecurityUtils.getUsername());
            this.updateById(cabinet);
        }

        return 1;
    }

    /**
     * 批量删除充电宝柜机
     *
     * @param list 柜机ID列表
     * @return 操作结果（1表示成功）
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int removeCabinet(List<Long> list) {
        // 逻辑删除柜机主记录
        this.removeByIds(list);

        // 物理删除关联的插槽记录
        cabinetSlotMapper.delete(new LambdaQueryWrapper<CabinetSlot>().in(CabinetSlot::getCabinetId, list));

        return 1;
    }

    /**
     * 搜索未使用柜机
     */
    @Override
    public List<Cabinet> searchNoUseList(String keyword) {
        return baseMapper.selectList(new LambdaQueryWrapper<Cabinet>().like(StrUtil.isNotEmpty(keyword), Cabinet::getCabinetNo, keyword));
    }

    /**
     * 获取充电宝柜机全部详细信息
     */
    @Override
    public Map<String, Object> getAllInfo(Long id) {
        // 查询柜机信息
        Cabinet cabinet = this.getById(id);

        // 查询插槽信息
        List<CabinetSlot> cabinetSlotList = cabinetSlotMapper.selectList(new LambdaQueryWrapper<CabinetSlot>().eq(CabinetSlot::getCabinetId, cabinet.getId()));

        // 获取可用充电宝id列表
        List<Long> powerBankIdList = cabinetSlotList.stream().filter(item -> null != item.getPowerBankId()).map(CabinetSlot::getPowerBankId).collect(Collectors.toList());

        if (!CollectionUtils.isEmpty(powerBankIdList)) {
            List<PowerBank> powerBankList = powerBankService.listByIds(powerBankIdList);

            Map<Long, PowerBank> powerBankIdToPowerBankMap = powerBankList.stream().collect(Collectors.toMap(PowerBank::getId, PowerBank -> PowerBank));

            cabinetSlotList.forEach(item -> item.setPowerBank(powerBankIdToPowerBankMap.get(item.getPowerBankId())));
        }

        return Map.of("cabinet", cabinet, "cabinetSlotList", cabinetSlotList);
    }

    /**
     * 构建柜机查询条件
     */
    private LambdaQueryWrapper<Cabinet> buildCabinetQueryWrapper(Cabinet cabinet) {
        LambdaQueryWrapper<Cabinet> wrapper = new LambdaQueryWrapper<>();

        // 机柜编号
        if (StrUtil.isNotEmpty(cabinet.getCabinetNo())) {
            wrapper.eq(Cabinet::getCabinetNo, cabinet.getCabinetNo());
        }

        // 名称
        if (StrUtil.isNotEmpty(cabinet.getName())) {
            wrapper.like(Cabinet::getName, cabinet.getName());
        }

        // 类别ID
        if (cabinet.getCabinetTypeId() != null) {
            wrapper.eq(Cabinet::getCabinetTypeId, cabinet.getCabinetTypeId());
        }

        // 状态（0：未投入 1：使用中 -1：故障）
        if (StrUtil.isNotEmpty(cabinet.getStatus())) {
            wrapper.eq(Cabinet::getStatus, cabinet.getStatus());
        }

        // 数据权限过滤（示例：只查询未删除的记录）
        wrapper.eq(Cabinet::getDelFlag, "0");

        return wrapper;
    }

    /**
     * 批量设置柜机类型名称
     */
    private void setCabinetTypeNames(List<Cabinet> cabinetList) {
        // 提取所有柜机类型ID
        Set<Long> typeIds = cabinetList.stream().map(Cabinet::getCabinetTypeId).filter(Objects::nonNull).collect(Collectors.toSet());

        if (typeIds.isEmpty()) {
            return;
        }

        // 批量查询柜机类型
        LambdaQueryWrapper<CabinetType> typeQueryWrapper = new LambdaQueryWrapper<>();
        typeQueryWrapper.in(CabinetType::getId, typeIds).eq(CabinetType::getDelFlag, "0");

        List<CabinetType> cabinetTypes = cabinetTypeMapper.selectList(typeQueryWrapper);

        // 构建ID到类型的映射
        Map<Long, String> typeNameMap = cabinetTypes.stream().collect(Collectors.toMap(CabinetType::getId, CabinetType::getName, (k1, k2) -> k1));

        // 设置柜机类型名称
        cabinetList.forEach(cabinet -> {
            if (cabinet.getCabinetTypeId() != null) {
                cabinet.setCabinetTypeName(typeNameMap.get(cabinet.getCabinetTypeId()));
            }
        });
    }
}
